package com.xique.park.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.xique.common.core.domain.R;
import com.xique.common.core.enums.PayType;
import com.xique.common.core.utils.AliossUtil;
import com.xique.common.core.utils.SecurityUtils;
import com.xique.common.core.web.domain.PageResult;
import com.xique.park.bean.dto.ParkInDto;
import com.xique.park.bean.dto.ParkOutDto;
import com.xique.park.bean.request.web.onDuty.OnDutySettlementRequest;
import com.xique.park.bean.vo.web.onDuty.OnDutySettlementVo;
import com.xique.park.bean.vo.web.payOrder.PayOrderVo;
import com.xique.park.controller.client.web.service.service.IOpengateRecordsService;
import com.xique.park.service.service.*;
import com.xique.system.api.RemoteSystemUserService;
import com.xique.system.api.dto.SystemUserDTO;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * 值班结算服务实现
 *
 * @author wld
 * @date 2022/3/17 11:07
 */
@RequiredArgsConstructor
@Service
public class OnDutySettlementServiceImpl implements IOnDutySettlementService {

    private final IPayOrderService payOrderService;

    private final IOpengateRecordsService opengateRecordreervice;

    private final IParkInService parkInService;

    private final IParkOutService parkOutService;

    private final RemoteSystemUserService remoteSystemUserService;

    private final AliossUtil aliossUtil;

    @Override
    public PageResult selectList(OnDutySettlementRequest request) {
        int pageNum = request.getPageNum();
        int pageSize = request.getPageSize();
        Long clientUserId = request.getClientUserId();
        String beginTime = request.getStartTime();
        String endTime = request.getEndTime();
        Long parkId = SecurityUtils.getParkId();

        SystemUserDTO systemUserDTO = new SystemUserDTO();
        systemUserDTO.setUserId(clientUserId);
        systemUserDTO.setParkId(parkId);
        systemUserDTO.setPageNum(pageNum);
        systemUserDTO.setPageSize(pageSize);

        R<PageResult> result = remoteSystemUserService.selectPageList(systemUserDTO);
        PageResult clientUserPageResult = result.getData();

        @SuppressWarnings("unchecked")
        List<LinkedHashMap<String, Object>> systemUserDTOList = (List<LinkedHashMap<String, Object>>) clientUserPageResult.getList();

        List<OnDutySettlementVo> onDutySettlementList = new ArrayList<>();

        if (CollUtil.isNotEmpty(systemUserDTOList)) {
            systemUserDTOList.forEach(linkedHashMap -> {
                // 获取值班员信息
                int userId = (int) linkedHashMap.get("userId");
                String clientUserName = (String) linkedHashMap.get("userName");
                OnDutySettlementVo onDutySettlementVo = new OnDutySettlementVo();
                onDutySettlementVo.setClientUserId((long) userId);
                onDutySettlementVo.setClientUserName(clientUserName);

                // 获取金额信息
                List<String> payTypeList = Arrays.asList(PayType.CASH.getType(), PayType.FREE.getType());
                PayOrderVo payOrderVo = payOrderService.selectStatisticsInfoByClientUserId((long) userId, payTypeList, beginTime, endTime);

                // 获取免费金额信息
                BigDecimal freeFee = payOrderService.selectFreeFee(parkId, userId, beginTime, endTime);
                onDutySettlementVo.setFreeFee(freeFee);

                // 获取现金放行金额信息
                BigDecimal noPayFee = payOrderService.selectNoPayFee(parkId, userId, beginTime, endTime);
                onDutySettlementVo.setNoPayFee(noPayFee);

                // 获取手动开闸信息
                int count = opengateRecordreervice.selectCountByClientUser((long) userId, beginTime, endTime);
                onDutySettlementVo.setOpenGateNum(count);

                if (payOrderVo != null) {
                    onDutySettlementVo.setCashFee(payOrderVo.getCashFee());
                    onDutySettlementVo.setCashSettlementFee(payOrderVo.getCashSettlementFee());
                    onDutySettlementVo.setNoCashSettlementFee(onDutySettlementVo.getCashFee().add(onDutySettlementVo.getFreeFee()).subtract(onDutySettlementVo.getCashSettlementFee()));
                } else {
                    onDutySettlementVo.setCashFee(BigDecimal.ZERO);
                    onDutySettlementVo.setCashSettlementFee(BigDecimal.ZERO);
                    onDutySettlementVo.setNoCashSettlementFee(BigDecimal.ZERO);
                }

                onDutySettlementList.add(onDutySettlementVo);
            });

        }

        return PageResult.builder()
                .pageNum(pageNum)
                .pageSize(pageSize)
                .totalPages(clientUserPageResult.getTotalPages())
                .totalSize(clientUserPageResult.getTotalSize())
                .list(onDutySettlementList)
                .build();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateCashSettlementFeeByClientUserId(Long clientUserId) {
        payOrderService.updateCashSettlementFeeByClientUserId(clientUserId);
    }

    @Override
    public PageResult selectFreeList(OnDutySettlementRequest request) {
        Long clientUserId = request.getClientUserId();
        String plate = request.getPlate();
        String payType = PayType.FREE.getType();
        Integer pageNum = request.getPageNum();
        Integer pageSize = request.getPageSize();
        String beginTime = request.getStartTime();
        String endTime = request.getEndTime();

        // 查询免费放行和支付信息
        PageResult freeResult = payOrderService.selectPageListByPayType(clientUserId, plate, payType, pageNum, pageSize, beginTime, endTime);

        // 处理分页查询结果
        List<OnDutySettlementVo> onDutySettlementVoList = handleResult(freeResult);

        return PageResult.builder()
                .pageNum(pageNum)
                .pageSize(pageSize)
                .totalPages(freeResult.getTotalPages())
                .totalSize(freeResult.getTotalSize())
                .list(onDutySettlementVoList)
                .build();
    }

    @Override
    public PageResult selectNoChargeList(OnDutySettlementRequest request) {
        Long clientUserId = request.getClientUserId();
        String plate = request.getPlate();
        Integer pageNum = request.getPageNum();
        Integer pageSize = request.getPageSize();
        String beginTime = request.getStartTime();
        String endTime = request.getEndTime();

        // 查询未收费金额和支付信息
        PageResult freeResult = payOrderService.selectPageNoChargeList(clientUserId, plate, pageNum, pageSize, beginTime, endTime);

        // 处理分页查询结果
        List<OnDutySettlementVo> onDutySettlementVoList = handleResult(freeResult);

        return PageResult.builder()
                .pageNum(pageNum)
                .pageSize(pageSize)
                .totalPages(freeResult.getTotalPages())
                .totalSize(freeResult.getTotalSize())
                .list(onDutySettlementVoList)
                .build();
    }

    /**
     * 处理分页查询结果
     */
    private List<OnDutySettlementVo> handleResult(PageResult opengateRecordResult) {
        @SuppressWarnings("unchecked")
        List<PayOrderVo> payOrderVoList = (List<PayOrderVo>) opengateRecordResult.getList();
        List<OnDutySettlementVo> onDutySettlementVoList = new ArrayList<>();

        if (CollectionUtils.isNotEmpty(payOrderVoList)) {
            payOrderVoList.forEach(payOrderVo -> {
                OnDutySettlementVo onDutySettlementVo = new OnDutySettlementVo();
                onDutySettlementVo.setPlate(payOrderVo.getPlate());
                onDutySettlementVo.setAmt(payOrderVo.getAmt());
                onDutySettlementVo.setRemark(payOrderVo.getRemark());
                if (null == payOrderVo.getSettlementStatus()) {
                    onDutySettlementVo.setSettlementStatus(0);
                } else {
                    onDutySettlementVo.setSettlementStatus(payOrderVo.getSettlementStatus());
                }

                String parkingSerial = payOrderVo.getParkingSerial();

                // 处理进出场信息
                handleInAndOutInfo(onDutySettlementVo, SecurityUtils.getParkId(), parkingSerial);

                onDutySettlementVoList.add(onDutySettlementVo);
            });
        }
        return onDutySettlementVoList;
    }

    /**
     * 处理进出场信息
     */
    private void handleInAndOutInfo(OnDutySettlementVo onDutySettlementVo, Long parkId, String parkingSerial) {
        // 查询进场信息
        List<ParkInDto> parkInDtoList = parkInService.selectParkInByParkingSerial(parkId, parkingSerial);
        if (CollectionUtils.isNotEmpty(parkInDtoList)) {
            ParkInDto parkIn = parkInDtoList.get(0);
            onDutySettlementVo.setInTime(parkIn.getInTime());
            onDutySettlementVo.setInLaneName(parkIn.getLaneName());
            onDutySettlementVo.setMngType(parkIn.getMngType());
            onDutySettlementVo.setInTye(parkIn.getInType());
            onDutySettlementVo.setInPic(StrUtil.isNotBlank(parkIn.getInPic()) ? aliossUtil.getJzyGetObjectUrl(parkIn.getInPic()).toString() : "");
        }

        // 查询出场信息
        List<ParkOutDto> parkOutDtoList = parkOutService.selectParkOutByParkingSerial(parkId, parkingSerial);
        if (CollectionUtils.isNotEmpty(parkOutDtoList)) {
            ParkOutDto parkOut = parkOutDtoList.get(0);
            onDutySettlementVo.setOutTime(parkOut.getOutTime());
            onDutySettlementVo.setOutLaneName(parkOut.getLaneName());
            onDutySettlementVo.setTrafficStatus(1);
            onDutySettlementVo.setMngType(parkOut.getMngName());
            onDutySettlementVo.setOutType(parkOut.getOutType());
            onDutySettlementVo.setOutPic(StrUtil.isNotBlank(parkOut.getOutPic()) ? aliossUtil.getJzyGetObjectUrl(parkOut.getOutPic()).toString() : "");
        } else {
            onDutySettlementVo.setTrafficStatus(0);
        }
    }

}
